import scala.collection.mutable
import scala.util.control.Breaks._
import scala.util.Random
import scala.io.StdIn // 导入标准输入类，支持手动输入

object LibrarySystem extends App {
  // 1. 数据初始化
  case class Book(id: String, title: String, author: String, totalCopies: Int, var availableCopies: Int)

  case class BorrowRecord(
                           recordId: String,
                           readerId: String,
                           bookId: String,
                           borrowDate: String,
                           dueDate: String,
                           var renewCount: Int,
                           var returnDate: Option[String] = None
                         )

  case class Reader(id: String, name: String, var unpaidFines: Double = 0.0)

  // 初始化图书
  val books = mutable.Map[String, Book](
    "B001" -> Book("B001", "Scala编程", "Martin Odersky", 5, 3),
    "B002" -> Book("B002", "Java编程思想", "Bruce Eckel", 3, 1),
    "B003" -> Book("B003", "数据结构与算法", "Mark Allen Weiss", 4, 4),
    "B004" -> Book("B004", "机器学习实战", "Peter Harrington", 2, 0),
    "B005" -> Book("B005", "深入理解计算机系统", "Randal E. Bryant", 5, 5)
  )
  // 初始化读者
  val readers = mutable.Map[String, Reader](
    "R001" -> Reader("R001", "张三", 15.0),
    "R002" -> Reader("R002", "李四"),
    "R003" -> Reader("R003", "王五", 60.0) // 有未缴罚款
  )

  // 初始化借阅记录
  val borrowRecords = mutable.ListBuffer[BorrowRecord](
    BorrowRecord("BR001", "R001", "B002", "2025-10-01", "2025-10-15", 0),
    BorrowRecord("BR002", "R001", "B001", "2025-10-05", "2025-10-19", 1)
  )

  // 2. 辅助函数
  // 生成随机ID
  def generateId(prefix: String): String = s"$prefix${System.currentTimeMillis()}"

  // 检查图书是否可借
  def isBookAvailable(bookId: String): Boolean = {
    books.get(bookId).exists(_.availableCopies > 0)
  }

  // 询问用户是否继续（通用函数）
  def askContinue(operation: String): Boolean = {
    println(s"\n是否继续$operation？(y/n)")
    val input = StdIn.readLine().trim.toLowerCase
    input == "y" || input == "yes"
  }

  // 3. 核心功能实现
  // 读者登录（改为手动输入读者ID）
  def login(): Option[Reader] = {
    var reader: Option[Reader] = None
    var attempts = 0
    val maxAttempts = 3

    do {
      attempts += 1
      println(s"\n请输入读者ID（剩余尝试次数：${maxAttempts - attempts + 1}）：")
      val inputId = StdIn.readLine().trim // 手动输入读者ID

      reader = readers.get(inputId)
      if (reader.isDefined) {
        println(s"登录成功！欢迎 ${reader.get.name}（${reader.get.id}）")
        if (reader.get.unpaidFines > 0) {
          println(f"提醒：您有未缴罚款 ${reader.get.unpaidFines}%.2f 元")
        }
      } else {
        println(s"读者ID $inputId 不存在，请重新输入")
      }
    } while (reader.isEmpty && attempts < maxAttempts)
    reader
  }

  // 图书查询（改为手动输入关键词）
  def searchBooks(): List[Book] = {
    var results = List.empty[Book]
    var continueSearch = true

    do {
      println("\n请输入查询关键词（如：编程、数据、算法）：")
      val keyword = StdIn.readLine().trim // 手动输入查询关键词

      if (keyword.isEmpty) {
        println("关键词不能为空，请重新输入")
      } else {
        println(s"\n查询关键词：'$keyword'")

        // 执行查询
        results = books.values.filter { book =>
          book.title.contains(keyword) || book.author.contains(keyword)
        }.toList

        // 显示结果
        println(s"找到 ${results.size} 本相关图书：")
        results.foreach { book =>
          println(f"[${book.id}] ${book.title} (${book.author}) - 可借: ${book.availableCopies}/${book.totalCopies}")
        }

        // 没找到结果才继续查询，找到则停止
        continueSearch = results.isEmpty && askContinue("查询")
      }
    } while (continueSearch)

    results
  }

  // 图书借阅（优化循环终止条件，支持手动选择是否继续）
  def borrowBooks(reader: Reader, availableBooks: List[Book]): Int = {
    var borrowedCount = 0
    val maxBorrow = 5
    var continue = true

    // 检查未缴罚款
    if (reader.unpaidFines > 50) {
      println(s"\n无法借阅：您的未缴罚款 ${reader.unpaidFines} 元超过50元上限")
      return 0
    }

    while (continue && borrowedCount < maxBorrow && availableBooks.nonEmpty) {
      // 选择可借图书
      val available = availableBooks.filter(b => books(b.id).availableCopies > 0)

      if (available.nonEmpty) {
        // 显示可借图书列表，让用户选择
        println("\n可借图书列表：")
        available.zipWithIndex.foreach { case (book, idx) =>
          println(f"${idx + 1}. [${book.id}] ${book.title} - 可借: ${book.availableCopies}本")
        }
        println(s"请选择要借阅的图书序号（1-${available.size}），或输入0取消：")

        val choice = try {
          StdIn.readInt()
        } catch {
          case _: Exception => -1 // 输入非数字视为无效
        }

        if (choice >= 1 && choice <= available.size) {
          val selectedBook = available(choice - 1)
          println(s"\n正在借阅《${selectedBook.title}》...")

          // 更新图书库存
          books(selectedBook.id).availableCopies -= 1

          // 创建借阅记录
          val borrowDate = "2025-10-20"
          val dueDate = "2025-11-03" // 14天后到期
          borrowRecords += BorrowRecord(
            generateId("BR"),
            reader.id,
            selectedBook.id,
            borrowDate,
            dueDate,
            0
          )

          borrowedCount += 1
          println(s"借阅成功！到期日：$dueDate")
          println(s"当前已借阅 $borrowedCount 本，最多可借 $maxBorrow 本")

          // 询问是否继续借阅（手动选择）
          continue = borrowedCount < maxBorrow && askContinue("借阅")
        } else if (choice == 0) {
          println("已取消借阅")
          continue = false
        } else {
          println("无效选择，请重新操作")
        }
      } else {
        println("\n没有可借的图书了")
        continue = false
      }
    }

    borrowedCount
  }

  // 图书归还与罚款计算（优化循环终止条件）
  def returnBooks(reader: Reader): Int = {
    var returnedCount = 0
    var continue = true

    // 获取该读者的未归还记录
    val readerRecords = borrowRecords.filter(br =>
      br.readerId == reader.id && br.returnDate.isEmpty
    )

    if (readerRecords.isEmpty) {
      println("\n您没有需要归还的图书")
      return 0
    }

    while (continue && returnedCount < readerRecords.size) {
      // 显示未归还图书列表
      println("\n您的未归还图书：")
      readerRecords.zipWithIndex.foreach { case (record, idx) =>
        val book = books(record.bookId)
        println(f"${idx + 1}. [${book.id}] ${book.title} - 借阅日期：${record.borrowDate}，到期日：${record.dueDate}")
      }
      println(s"请选择要归还的图书序号（1-${readerRecords.size}），或输入0取消：")

      val choice = try {
        StdIn.readInt()
      } catch {
        case _: Exception => -1
      }

      if (choice >= 1 && choice <= readerRecords.size) {
        val record = readerRecords(choice - 1)
        val book = books(record.bookId)

        println(s"\n正在归还《${book.title}》...")

        // 模拟超期天数（0-20天随机）
        val overDays = Random.nextInt(21)
        if (overDays > 0) {
          // 计算罚款（每天0.5元，最多不超过图书价格30%）
          val dailyFine = 0.5
          val maxFine = book.totalCopies * 10 * 0.3 // 简化：假设单本价格10元
          val fine = math.min(overDays * dailyFine, maxFine)
          reader.unpaidFines += fine
          println(f"图书已超期 $overDays 天，需缴纳罚款 $fine%.2f 元")
          println(f"当前总未缴罚款：${reader.unpaidFines}%.2f 元")
        } else {
          println("图书按时归还，无需缴纳罚款")
        }

        // 更新记录和库存
        record.returnDate = Some("2025-10-20")
        book.availableCopies += 1

        returnedCount += 1
        println(s"归还成功！已归还 $returnedCount 本")

        // 询问是否继续归还
        continue = returnedCount < readerRecords.size && askContinue("归还")
      } else if (choice == 0) {
        println("已取消归还")
        continue = false
      } else {
        println("无效选择，请重新操作")
      }
    }

    returnedCount
  }

  // 4. 系统主流程
  println("===== 校园图书借阅系统 =====")

  // 登录流程
  val currentReader = login()
  if (currentReader.isEmpty) {
    println("登录失败，程序退出")
  } else {
    var running = true

    // 主循环：系统功能菜单（手动选择功能）
    while (running) {
      println("\n===== 功能菜单 =====")
      println("1. 图书查询与借阅")
      println("2. 图书归还")
      println("3. 退出系统")
      println("请选择功能序号（1-3）：")

      // 手动输入功能选择
      val choice = try {
        StdIn.readInt()
      } catch {
        case _: Exception => -1 // 输入非数字视为无效
      }

      choice match {
        case 1 =>
          val foundBooks = searchBooks()
          val borrowed = borrowBooks(currentReader.get, foundBooks)
          println(s"\n本次共借阅 $borrowed 本图书")

        case 2 =>
          val returned = returnBooks(currentReader.get)
          println(s"\n本次共归还 $returned 本图书")

        case 3 =>
          println("感谢使用，再见！")
          running = false // 退出主循环

        case _ =>
          println("无效选择，请输入1-3之间的数字")
      }
    }
  }
}
